﻿using ServiceStack.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
//Session分布式共享 = Session + Redis + Nginx
//http://www.cnblogs.com/newP/p/6518918.html
//Redis实战与 Session缓存
//http://www.cnblogs.com/zactor/archive/2017/03/02/6486679.html 
namespace Sessionwithredis.Controllers
{
    public class LoginController : Controller
    {
        // GET: Login
        public ActionResult Index()
        {
            return View();
        }
        public ActionResult Login()
        {
            //登录逻辑
            var userLoginInfo = new UserSession
            {
                Id = 12,
                Name = "Test",
                Permissions = new List<string> { "Home.page" }
            };
            SessionHelper<UserSession> _sessionHelper = new SessionHelper<UserSession>();
            var token = _sessionHelper.CreateSession(userLoginInfo);

            var cookie = new HttpCookie("User")
            {
                Expires = DateTime.Now.AddMinutes(20),
                Value = token
            };
            Response.AppendCookie(cookie);
            return View();
        }
    }

    internal class UserSession
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public List<string> Permissions { get; set; }
    }

    public class SessionHelper<T> : RedisHelper, ISessionHelper<T>
    {
        public T GetSession(string token)
        {
            return !string.IsNullOrEmpty(token) ? GetValue<T>(token) : default(T);
        }

        public string CreateSession(T value)
        {
            var guid = Guid.NewGuid().ToString("D");
            SetValue<T>(guid, value);

            return guid;
        }

        public void RemoveSession(string token)
        {
            Delete(token);
        }
    }

    internal interface ISessionHelper<T>
    {
    }

    public class RedisHelper : IRedisHelper
    {
        private readonly string _ip = "127.0.0.1";
        private readonly int _port = 6379;
        private readonly string _passWord = string.Empty;
        public int Expire { get; set; }

        public RedisHelper(int expireTime = 1200)
        {
            Expire = expireTime;
        }

        public RedisHelper(string ip, int port, string passWord, int expireTime = 1200)
        {
            _ip = ip;
            _port = port;
            _passWord = passWord;
            Expire = expireTime;
        }

        public T GetValue<T>(string key)
        {
            using (var redisClient = GetRedisClient())
            {
                return redisClient.Get<T>(key);
            }
        }

        public bool SetValue(string key, string value)
        {
            using (var redisClient = GetRedisClient())
            {
                if (!redisClient.Set(key, value)) return false;
                SetExpire(redisClient, key);
                return true;
            }
        }

        public void SetValue<T>(string key, T value)
        {
            using (var redisClient = GetRedisClient())
            {
                if (redisClient.Set<T>(key, value))
                    SetExpire(redisClient, key);
            }
        }

        public void Delete(string key)
        {
            using (var redisClient = GetRedisClient())
            {
                redisClient.Remove(key);
            }
        }

        private RedisClient GetRedisClient()
        {
            return new RedisClient(_ip, _port, _passWord);
        }

        private void SetExpire(IRedisNativeClient redisClient, string key)
        {
            redisClient.Expire(key, Expire);
        }
    }

    public interface IRedisHelper
    {
    }
}